//+------------------------------------------------------------------+
//| A table of sorted indices for arrays and vectors of arb. type.	|
//| Lightweight and fully inline.												|
//+------------------------------------------------------------------+
#pragma once
#include <vector>
#include <algorithm>

//+==================================================================+
class Index
{
public:
//+------------------------------------------------------------------+
	Index()									{											}
	Index(int size) : idx(size,0)		{											}
	template<class T>
	Index(const std::vector<T> &v)	{	index(v);							}
	template<class T>
	Index(const T *v, int size)		{	index(v, size);					}

//+------------------------------------------------------------------+
	void resize(int size)				{	idx.resize(size);					}

//+------------------------------------------------------------------+
	int&	operator[]						(int i)			{	return idx[i];	}
	int	operator[]						(int i)	const	{	return idx[i];	}
	operator const std::vector<int>&	()			const	{	return idx;		}
	operator const int*					()			const	{	return &idx[0];}

//+------------------------------------------------------------------+
	template<class T>
	void index(const std::vector<T> &v, bool descending = false)
	{
		index(&v[0], v.size(), descending);
	}

//+------------------------------------------------------------------+
	template<class T>
	void index(const T *v, unsigned size, bool descending = false)
	{
	//----
	//	resize index array
		if(idx.size()<size)
			idx.resize(size);

	//----
	//	initialize index array
		for(unsigned i = 0; i < size; ++i)
			idx[i] = i;

	//----
	//	sort index array
		if(descending)	std::sort(&idx[0], &idx[0]+size, cmp_greater<const T*>(v));
		else				std::sort(&idx[0], &idx[0]+size, cmp_less   <const T*>(v));
	}

private:
//+==================================================================+
//	the index table is the only member data
	std::vector<int> idx;

//	functor which is used as predicate for the sort function
	template<class T> struct cmp_less
	{
		const T arr;
		cmp_less(const T arr) : arr(arr)		{									}
		bool operator()(int a, int b) const	{	return arr[a] < arr[b];	}
	};

//	functor which is used as predicate for the sort function
	template<class T> struct cmp_greater
	{
		const T arr;
		cmp_greater(const T arr) : arr(arr)	{									}
		bool operator()(int a, int b) const	{	return arr[a] > arr[b];	}
	};
};

